/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package util;

import core.ErrorLogger;
import core.Visit;
import java.awt.Color;
import java.awt.Component;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.table.TableCellRenderer;

/**
 *
 * @author Marcin
 */



public class JCalendar {
    public static enum CellType{
        VISIT,
        HOLIDAY,
        NORMAL,
        HOMEVISIT,
        AVAILABLE
    }
    public static class Hour{
        private int hour;
        private int minutes;
        public Hour(int date)
        {
            this.hour = date/60;
            this.minutes = date%60;
        }
        public Hour(int hour,int minutes)
        {
            this.hour = hour;
            this.minutes = minutes;
        }
        public int getHour()
        {
            return hour;
        }
        public int getMinutes()
        {
            return minutes;
        }
        @Override
        public String toString()
        {
            if(minutes!=0) {
                return Integer.valueOf(hour).toString() +":" + Integer.valueOf(minutes);
            }
            else {
                return Integer.valueOf(hour).toString() +":00";
            }
        }
    }
    private String[] columnNames = new String[]
    {
            "Godzina",
            "Poniedziałek",
            "Wtorek",
            "Środa",
            "Czwartek",
            "Piątek",
            "Sobota",
            "Niedziela"
    };
    
    private int rowcount;
    CellType[][] calendarMap;
    private JTable calendar;
    private GregorianCalendar date;
    private int  minutesSeparate;
    /**
     * Konstruktor kalendarza
     * @param fromHour Od której godziny ma stworzyć kalenarz
     * @param toHour Do której godziny ma stworzyć kalendarz
     * @param minutesSeparate ile bedzie kolumn(ilosc minut / minutesSeparete)
     */
    public JCalendar(Hour fromHour,Hour toHour,int minutesSeparate)
    {
        date = new GregorianCalendar();
        this.minutesSeparate = minutesSeparate;
        int minutes = 60*toHour.getHour() + toHour.getMinutes();
        minutes -= 60*fromHour.getHour() + fromHour.getMinutes();
        rowcount = minutes/minutesSeparate;
        Object[][] data = new Object[rowcount][8];
        calendarMap = new CellType[rowcount][8];
        for(int i=0;i<rowcount;i++)
        {
            Arrays.fill(calendarMap[i], CellType.NORMAL);
            data[i][0] = new Hour(fromHour.getHour()*60+fromHour.minutes + i*minutesSeparate).toString();
            Arrays.fill(data[i], 1,8,"");
        }
        calendar = new JTable(data,columnNames)
        {
            @Override
            public boolean isCellEditable(int rowIndex, int colIndex) {
                return false;
            }
            @Override
            public boolean isCellSelected(int rowIndex, int colIndex) {
                if(colIndex == 0) {
                    return false;
                }
                else {
                    return super.isCellSelected(rowIndex, colIndex);
                }   
            }
            @Override
           
            public Component prepareRenderer (TableCellRenderer renderer, int rowIndex, int colIndex){ 
                Component comp = super.prepareRenderer(renderer, rowIndex, colIndex);
                if( calendarMap[rowIndex][colIndex] == CellType.NORMAL ){ 
                    if(rowIndex%2==1) {
                        comp.setBackground(Color.decode("-855310"));
                    }
                    else {
                        comp.setBackground(Color.WHITE);
                    }
                } else if(calendarMap[rowIndex][colIndex] == CellType.HOLIDAY) { 
                    comp.setBackground(Color.YELLOW); 
                }
                else if(calendarMap[rowIndex][colIndex] == CellType.VISIT) { 
                    comp.setBackground(Color.CYAN); 
                }
                else if(calendarMap[rowIndex][colIndex] == CellType.AVAILABLE) { 
                    comp.setBackground(Color.GREEN); 
                }
                else if(calendarMap[rowIndex][colIndex] == CellType.HOMEVISIT)
                {
                    comp.setBackground(Color.orange);
                }
                if(isCellSelected(rowIndex,colIndex))
                {
                    comp.setBackground(Color.decode("-13014646"));
                }
                return comp;
            }            
        };
        calendar.setColumnSelectionAllowed(true);
        calendar.setRowSelectionAllowed(true);
        calendar.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
    }    
    public JTable getCalendar()
    {
        return calendar;
    }
    
    public Date getSelectedDateStart(int c)
    {
         Calendar cal = new GregorianCalendar();
         int row[] = calendar.getSelectedRows();
         Calendar tmp = new GregorianCalendar();
         tmp.setTime(getFirstDayOfWeek(date));
         tmp.roll(Calendar.DAY_OF_YEAR, c-1);
         cal.set(tmp.get(Calendar.YEAR), tmp.get(Calendar.MONTH), tmp.get(Calendar.DAY_OF_MONTH), Integer.parseInt(calendar.getValueAt(row[0], 0).toString().split(":")[0])
                 , Integer.parseInt(calendar.getValueAt(row[0], 0).toString().split(":")[1]),0);
         cal.set(Calendar.MILLISECOND, 0);
         
         return cal.getTime();
    }
    
    public Date getSelectedDateStart2(int c)
    {
         Calendar cal = new GregorianCalendar();
         int row[] = calendar.getSelectedRows();
         Calendar tmp = new GregorianCalendar();
         tmp.setTime(getFirstDayOfWeek(date));
         tmp.roll(Calendar.DAY_OF_YEAR, c-1);
         int i = row[0];
         while(calendar.getValueAt(i--, c) == ""){}
         cal.set(tmp.get(Calendar.YEAR), tmp.get(Calendar.MONTH), tmp.get(Calendar.DAY_OF_MONTH), Integer.parseInt(calendar.getValueAt(i+1, 0).toString().split(":")[0])
                 , Integer.parseInt(calendar.getValueAt(i+1, 0).toString().split(":")[1]),0);
         cal.set(Calendar.MILLISECOND, 0);
         return cal.getTime();
    }
    
    public Date getSelectedDateEnd(int c)
    {
         Calendar cal = new GregorianCalendar();
         int row[] = calendar.getSelectedRows();
                  Calendar tmp = new GregorianCalendar();
         tmp.setTime(getFirstDayOfWeek(date));
         tmp.roll(Calendar.DAY_OF_YEAR, c-1);
         cal.set(tmp.get(Calendar.YEAR), tmp.get(Calendar.MONTH), tmp.get(Calendar.DAY_OF_MONTH), Integer.parseInt(calendar.getValueAt(row[row.length-1], 0).toString().split(":")[0])
                 , Integer.parseInt(calendar.getValueAt(row[row.length-1]+1, 0).toString().split(":")[1]),0);
         cal.set(Calendar.MILLISECOND, 0);
         return cal.getTime();
    }
    
    public void nextWeek()
    {
        date.add(Calendar.DAY_OF_YEAR, 7);
        
    }
 
    public void prevWeek()
    {
        date.add(Calendar.DAY_OF_YEAR, -7);
    }
    
    public Date getFirstDayOfWeek(Calendar cal)
    {
        GregorianCalendar tmp = new GregorianCalendar();
        tmp.set(Calendar.YEAR, cal.get(Calendar.YEAR));
        tmp.set(Calendar.WEEK_OF_YEAR, cal.get(Calendar.WEEK_OF_YEAR));
        tmp.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
        tmp.set(Calendar.HOUR_OF_DAY, 0);
        tmp.set(Calendar.MINUTE, 0);
        tmp.set(Calendar.SECOND, 0);
        return tmp.getTime();
    }

    public Date getLastDayOfWeek(Calendar cal)
    {
        GregorianCalendar tmp = new GregorianCalendar();
        tmp.set(Calendar.YEAR, cal.get(Calendar.YEAR));
        tmp.set(Calendar.WEEK_OF_YEAR, cal.get(Calendar.WEEK_OF_YEAR));
        tmp.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY);
        tmp.set(Calendar.HOUR_OF_DAY, 23);
        tmp.set(Calendar.MINUTE, 59);
        tmp.set(Calendar.SECOND, 59);
        return tmp.getTime();
    }
    
    public Calendar getDate()
    {
        return date;
    }
    
    public void clear()
    {
        for(int i=0;i<rowcount;i++)
        {
            for(int j=1;j<calendar.getColumnCount();j++)
            {
                calendar.setValueAt("", i, j);
            }
            Arrays.fill(calendarMap[i], CellType.NORMAL);      
        }
    }
    
    public void repaint()
    {
        calendar.repaint();
    }
    
    public void update(ResultSet rs,CellType cellType)
    {
        try {
            rs.next();
            while(rs.next())
            {
                Timestamp start = rs.getTimestamp("data_start");
                Timestamp end = rs.getTimestamp("data_stop");
                Calendar cal_s = new GregorianCalendar();
                cal_s.setTime(start);
                Calendar cal_e = new GregorianCalendar();
                cal_e.setTime(end);
                Calendar tmp = new GregorianCalendar();
                tmp.setTime(start);
                tmp.set(Calendar.HOUR_OF_DAY,Integer.parseInt(calendar.getValueAt(0, 0).toString().split(":")[0]));
                tmp.set(Calendar.MINUTE,Integer.parseInt(calendar.getValueAt(0, 0).toString().split(":")[1]));
                int i=0;
                boolean write = false;
                while(tmp.compareTo(cal_s) == -1)
                {
                    i++;
                    tmp.add(Calendar.MINUTE, minutesSeparate);
                }
                while(cal_s.compareTo(cal_e) != 0)
                {
                    if(!write)
                    {
                        if(CellType.HOLIDAY == cellType){
                            calendar.setValueAt("Wolne", i, getColFromDay(cal_s.get(Calendar.DAY_OF_WEEK)));
                            write = true;
                        }
                        if(CellType.VISIT == cellType)
                        {
                            Visit vis = new Visit();
                            ResultSet room = vis.getRoomDetail(rs.getInt("id_gabinetu"));
                            if(room.next()) {
                                calendar.setValueAt(room.getString("nazwa"), i, getColFromDay(cal_s.get(Calendar.DAY_OF_WEEK)));
                            }
                            write = true;
                        }
                    }
                    if(cellType != CellType.AVAILABLE)
                        calendarMap[i++][getColFromDay(cal_s.get(Calendar.DAY_OF_WEEK))] = cellType;
                    else
                        calendarMap[i++][getDayFromString(rs.getString("dzien"))] = cellType;
                    cal_s.add(Calendar.MINUTE, minutesSeparate);
                }
            }
        } catch (SQLException ex) {
            ErrorLogger.getInstance().log(ex.getMessage(), true, null);
        }    
    }
    private int getColFromDay(int day)
    {
        switch(day){
            case Calendar.MONDAY:
            return 1;
            case Calendar.THURSDAY:
            return 4;
            case Calendar.FRIDAY:
            return 5;
            case Calendar.SATURDAY:
            return 6;
            case Calendar.SUNDAY:
            return 7;
            case Calendar.WEDNESDAY:
            return 3;
            case Calendar.TUESDAY:
            return 2;
            default :
                return -1;
        }
    }
    
    private int getDayFromString(String day)
    {
        switch(day)
        {
            case "Poniedziałek":
                return 1;
            case "Wtorek":
                return 2;
            case "Środa":
                return 3;
            case "Czwartek":
                return 4;
            case "Piątek":
                return 5;
            case "Sobota":
                return 6;
            case "Niedziela":
                return 7;
            default:
                return -1;
        }
    }
    
    public void addEvent(CellType cellType)
    {
        int col[] = calendar.getSelectedColumns();
        int row[] = calendar.getSelectedRows();
        for(int i=0;i<col.length;i++)
        {
            for(int j=0;j<row.length;j++)
            {
                if(col[i]!=0) {
                    calendarMap[row[j]][col[i]] = cellType;
                }
            }
        }
    }
}
